use std::env;
use std::fs;
use std::path::Path;

fn main() {
    // 确保bin目录存在
    let current_dir = env::current_dir().unwrap_or_default();
    let bin_dir = format!("{}/../bin", current_dir.display());
    fs::create_dir_all(&bin_dir).unwrap_or_else(|e| {
        println!("cargo:warning=创建bin目录失败: {}", e);
    });
    
    // 启用所有优化标志
    println!("cargo:rustc-env=RUSTFLAGS=-C target-cpu=native -C opt-level=3");
    
    // Windows特定：链接系统库
    #[cfg(target_os = "windows")]{
        println!("cargo:rustc-link-lib=dylib=msvcrt");
        println!("cargo:rustc-link-lib=dylib=ucrt");
        println!("cargo:rustc-link-lib=dylib=vcruntime");
        println!("cargo:rustc-link-lib=dylib=user32");
        println!("cargo:rustc-link-lib=dylib=kernel32");
    }
    
    // 通用系统库
    #[cfg(not(target_os = "windows"))]{
        println!("cargo:rustc-link-lib=dylib=c");
        println!("cargo:rustc-link-lib=dylib=m");
    }
    
    // 链接Pipit C标准库（当use_c_stdlib特性启用时）
    #[cfg(feature = "use_c_stdlib")]{
        let stdlib_dir = env::var("CARGO_MANIFEST_DIR").unwrap_or(".".to_string());
        let lib_dir = format!("{}/../stdlib/c/lib", stdlib_dir);
        
        // 输出诊断信息
        println!("cargo:warning=链接到Pipit C标准库，目录: {}", lib_dir);
        println!("cargo:warning=目标操作系统: {}", std::env::consts::OS);
        
        // 为Windows平台提供特殊的链接配置
        #[cfg(target_os = "windows")]{
            // 尝试链接到动态库
            println!("cargo:rustc-link-search=native={}", lib_dir);
            println!("cargo:rustc-link-lib=dylib=pipit_stdlib");
            
            // 尝试链接到静态库，确保有一个能成功
            println!("cargo:rustc-link-lib=static=pipit_stdlib");
            
            // 复制DLL到多个可能的输出目录
            let dll_path = format!("{}/libpipit_stdlib.dll", lib_dir);
            
            // 复制到bin目录（主输出目录）
            let bin_dll_path = format!("{}/libpipit_stdlib.dll", bin_dir);
            println!("cargo:warning=复制DLL到bin目录: {} -> {}", dll_path, bin_dll_path);
            
            // 复制到target/debug目录（用于调试构建）
            let debug_dir = format!("{}/target/debug", stdlib_dir);
            let debug_dll_path = format!("{}/libpipit_stdlib.dll", debug_dir);
            
            // 复制到target/release目录（用于发布构建）
            let release_dir = format!("{}/target/release", stdlib_dir);
            let release_dll_path = format!("{}/libpipit_stdlib.dll", release_dir);
            
            // 确保目标目录存在
            fs::create_dir_all(&debug_dir).unwrap_or_default();
            fs::create_dir_all(&release_dir).unwrap_or_default();
            
            // 尝试复制DLL文件（如果存在）
            if std::path::Path::new(&dll_path).exists() {
                // 复制到bin目录
                match std::fs::copy(&dll_path, &bin_dll_path) {
                    Ok(_) => println!("cargo:warning=DLL复制到bin目录成功"),
                    Err(e) => println!("cargo:warning=DLL复制到bin目录失败: {}", e),
                }
                
                // 复制到debug目录
                match std::fs::copy(&dll_path, &debug_dll_path) {
                    Ok(_) => println!("cargo:warning=DLL复制到debug目录成功"),
                    Err(e) => println!("cargo:warning=DLL复制到debug目录失败: {}", e),
                }
                
                // 复制到release目录
                match std::fs::copy(&dll_path, &release_dll_path) {
                    Ok(_) => println!("cargo:warning=DLL复制到release目录成功"),
                    Err(e) => println!("cargo:warning=DLL复制到release目录失败: {}", e),
                }
            } else {
                println!("cargo:warning=DLL文件不存在: {}", dll_path);
            }
        }
        
        // 为非Windows平台提供链接配置
        #[cfg(not(target_os = "windows"))]{
            println!("cargo:rustc-link-search=native={}", lib_dir);
            println!("cargo:rustc-link-lib=static=pipit_stdlib");
        }
        
        println!("cargo:rerun-if-changed={}", lib_dir);
    }
    
    // JIT预编译阶段
    precompile_core_modules();
    
    println!("cargo:rerun-if-changed=build.rs");
    println!("cargo:rerun-if-changed=src/");
}

fn precompile_core_modules() {
    let out_dir = env::var("OUT_DIR").unwrap();
    let precompile_dir = Path::new(&out_dir).join("precompiled");
    fs::create_dir_all(&precompile_dir).unwrap();
    
    // 预编译标准库模块
    let stdlib_modules = vec![
        ("math", generate_math_bytecode()),
        ("io", generate_io_bytecode()),
        ("string", generate_string_bytecode()),
    ];
    
    for (name, bytecode) in stdlib_modules {
        let output_path = precompile_dir.join(format!("{}.pre", name));
        fs::write(output_path, bytecode).unwrap();
    }
}

// 生成数学库字节码
fn generate_math_bytecode() -> Vec<u8> {
    let mut bytecode = Vec::new();
    
    // 简单的加法函数
    bytecode.extend_from_slice(&[0x01, 0x00, 0x00, 0x00, 0x00]); // PushInt 0
    bytecode.extend_from_slice(&[0x01, 0x01, 0x00, 0x00, 0x00]); // PushInt 1
    bytecode.extend_from_slice(&[0x02]); // Add
    bytecode.extend_from_slice(&[0x06]); // Print
    bytecode.extend_from_slice(&[0x07]); // Halt
    
    bytecode
}

// 生成IO库字节码
fn generate_io_bytecode() -> Vec<u8> {
    let mut bytecode = Vec::new();
    
    // 简单的打印函数
    bytecode.extend_from_slice(&[0x01, 0x48, 0x65, 0x6C, 0x6C]); // PushInt 'H'
    bytecode.extend_from_slice(&[0x06]); // Print
    bytecode.extend_from_slice(&[0x07]); // Halt
    
    bytecode
}

// 生成字符串库字节码
fn generate_string_bytecode() -> Vec<u8> {
    let mut bytecode = Vec::new();
    
    // 字符串处理函数
    bytecode.extend_from_slice(&[0x01, 0x00, 0x00, 0x00, 0x00]); // PushInt 0
    bytecode.extend_from_slice(&[0x08, 0x00, 0x00, 0x00, 0x00]); // StoreVar 0
    bytecode.extend_from_slice(&[0x09, 0x00, 0x00, 0x00, 0x00]); // LoadVar 0
    bytecode.extend_from_slice(&[0x06]); // Print
    bytecode.extend_from_slice(&[0x07]); // Halt
    
    bytecode
}